<?php

use Maatwebsite\Excel\Facades\Excel;
use App\Exports\ExcelExport;
use Ramsey\Uuid\Uuid;
use GuzzleHttp\Client;

function isPhone($phone){
    return preg_match(config('Preg.phone'),$phone)===1;
}

/**
 * 仅返回一维数组中的某些字段
 * @param array $array 一维数组
 * @param array $keys
 * @return mixed
 */
function array_only($array,$keys){
    if (!$array) return $array;
    foreach($array as $key=>$val){
        if (!in_array($key,$keys)){
            unset($array[$key]);
        }
    }
    return $array;
}

/**
 * 仅返回二维数组中的某些字段
 * @param array $array2 二维数组
 * @param array $keys
 * @return mixed
 */
function array2_only($array2, $keys){
    foreach($array2 as $key=>$array){
        $array2[$key] = array_only($array,$keys);
    }
    return $array2;
}
function strArrToIntArr($arr){
    foreach($arr as &$value){
        $value = (int)$value;
    }
    return $arr;
}

/**
 * @param string $uri
 * @param array $params
 * @param array $additional 附加数据
 * @return mixed|null
 */
function callRpc($uri ='',$params = [], $additional = [])
{
    $body = [];
    try {
        $client = new Client();
        $body = [];
        $body['params'] = $params;
        $body['additional'] = $additional;
        $server = config('app.swoole_rpc_host') . ':' . config('app.swoole_rpc_port');
        $response = $client->post("http://".$server . $uri ,[
            'headers'=>[
                'Content-type'=>'application/json',
            ],
            'json'=>$body,
        ]);
        $content = $response->getBody()->getContents();
        return json_decode($content,true);
    } catch (\GuzzleHttp\Exception\GuzzleException $e) {
        \Illuminate\Support\Facades\Log::error( "callRpc Error, msg: " . $e->getMessage() );
        \Illuminate\Support\Facades\Log::error( "callRpc Error, data: " . json_encode($body) );
        return null;
    }
}

function is_mobile(){
    if (isset($_SERVER['HTTP_USER_AGENT'])) {
        $user_agent = $_SERVER['HTTP_USER_AGENT'];
        $mobile_agents = Array("Android", "iPhone", "iPod", "iPad", "Windows Phone", "BlackBerry", "SymbianOS");
        foreach ($mobile_agents as $mobile_agent) {
            if (strpos($user_agent, $mobile_agent) !== false) {
                return true;
            }
        }
    }
    return false;
}

/** 根据roleId获取游戏角色和游戏账号
 * @param $roleId 角色ID
 * @return array ['userMember'=>[],'userRole'=>[]]
 * @throws Exception
 */
function getMemAndRoleByRoleId($roleId){
    $userRoleService = new \App\Services\Game\UserRoleService();
    $userMemberService = new \App\Services\Game\UserMemberService();
    $userRole = $userRoleService->getById($roleId,['id','memid','nick']);
    if (!$userRole){
        throw new \Exception("角色不存在");
    }
    $memId = data_get($userRole,'memid');
    $member = $userMemberService->getById($memId);
    if (empty($member)){
        throw new \Exception("账号不存在");
    }
    return ['userMember'=>$member,'userRole'=>$userRole];
}

//异常处理
function exceptionDispose(Throwable $e)
{
    \App\Utils\MyLog::error(date("Y-m-d H:i:s") . " file: {$e->getFile()} line:{$e->getLine()} msg: {$e->getMessage()} \n");
}

function isValidDateTimeFormat($datetime, $format='Y-m-d H:i:s') {
    $dateObj = DateTime::createFromFormat($format, $datetime);
    return $dateObj !== false && !array_sum($dateObj->getLastErrors());
}


function exportExcel($excelRows,$fileName){
    $excel = new ExcelExport($excelRows);
    return Excel::download($excel, $fileName.'.xlsx');
}

function exportCsv($excelRows , $fileName='csv'){
    $content = "";
    foreach($excelRows as $excelRow) {
        $csvRow = '"' . implode('","', $excelRow) . '"';
        $content .= $csvRow . "\n";
    }
    //输出文件
    $headers = [
        'Content-Type' => 'application/octet-stream',
        'Content-Disposition' => "attachment; filename=.scv; filename*=utf-8''". urlencode($fileName) . ".csv",
    ];
    return response()->stream(function () use ($content) {
        echo $content;
    }, 200,$headers);
}

/**
 * @param array $rows 二维数组
 * @return string 符合scv格式的字符串
 */
function arrayToScvContent($rows){
    $content = "";
    foreach($rows as $row) {
        $csvRow = '"' . implode('","', $row) . '"';
        $content .= $csvRow . "\n";
    }
    return $content;
}

function arrayToScvContentString($rows) {
    $content = "";
    foreach ($rows as $row) {
        $csvRow = [];
        foreach ($row as $cell) {
            // 将每个单元格的值转换为字符串
            $csvRow[] = '"' . $cell . '"';
        }
        $csvRow = implode(',', $csvRow);
        $content .= $csvRow . "\n";
    }
    return $content;
}
/**
 * @param string $content 文件内容
 * @param string $suffix 文件后缀
 * @return string 返回随机文件名
 */
function cacheDownload(string $content, $suffix){ //缓存下载文件 , 返回文件名
    $fileName = Uuid::uuid4().$suffix;
    $filePath = 'cacheDownload/'.$fileName;
    $dirname = dirname($filePath);
    \Illuminate\Support\Facades\Log::info("file path: " . $filePath);
    if (!file_exists($dirname)) mkdir($dirname,0777);
    file_put_contents($filePath,$content);
    return 'cacheDownload/'.$fileName;
}

function uploadFiletc($filePath, $additionalParam)
{   //61.160.195.35
    $url = 'http://192.168.0.56:50005/special-upload';
    $curl = curl_init();

    // 设置 CURL 选项
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HEADER, false);

    // 输出当前工作目录
    \App\Utils\MyLog::info('当前工作目录: ' . getcwd());

    // 输出上传文件路径
    \App\Utils\MyLog::info('上传文件路径: ' . $filePath);

    // 检查文件是否存在
    if (!file_exists($filePath)) {
        throw new \Exception('文件不存在: ' . $filePath);
    }
    if (filesize($filePath) === 0) {
        throw new \Exception('文件为空: ' . $filePath);
    }
    \App\Utils\MyLog::info('文件大小'.json_encode(filesize($filePath) ));
    // 文件上传
    $cfile = new CURLFile($filePath);
    if (!$cfile instanceof CURLFile) {
        throw new \Exception('CURLFile 对象创建失败');
    }
    $data = [
        'files' => $cfile,
        'path' => $additionalParam
    ];
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    \App\Utils\MyLog::info('推送到服务器');

    // 执行 CURL 请求
    $response = curl_exec($curl);
    \App\Utils\MyLog::info('返回请求' . json_encode($response));

    if (curl_errno($curl)) {
        throw new \Exception('Curl error: ' . curl_error($curl));
    }

    curl_close($curl);
    return $response; // 可根据需要处理响应
}

function uploadFile($filePath, $additionalParam)
{   //61.160.195.35
    $url = 'http://192.168.0.47:50005/special-upload';
    $curl = curl_init();

    // 设置 CURL 选项
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HEADER, false);

    // 输出当前工作目录
    \App\Utils\MyLog::info('当前工作目录: ' . getcwd());

    // 输出上传文件路径
    \App\Utils\MyLog::info('上传文件路径: ' . $filePath);

    // 检查文件是否存在
    if (!file_exists($filePath)) {
        throw new \Exception('文件不存在: ' . $filePath);
    }
    if (filesize($filePath) === 0) {
        throw new \Exception('文件为空: ' . $filePath);
    }
    \App\Utils\MyLog::info('文件大小'.json_encode(filesize($filePath) ));
    // 文件上传
    $cfile = new CURLFile($filePath);
    if (!$cfile instanceof CURLFile) {
        throw new \Exception('CURLFile 对象创建失败');
    }
    $data = [
        'files' => $cfile,
        'path' => $additionalParam
    ];
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    \App\Utils\MyLog::info('推送到服务器');

    // 执行 CURL 请求
    $response = curl_exec($curl);
    \App\Utils\MyLog::info('返回请求' . json_encode($response));

    if (curl_errno($curl)) {
        throw new \Exception('Curl error: ' . curl_error($curl));
    }

    curl_close($curl);
    return $response; // 可根据需要处理响应
}
function uploadFileqd($filePath, $additionalParam)
{   //61.160.195.35 正式服 192.168.0.47
    $url = 'http://192.168.0.47:50006/special-upload';
    $curl = curl_init();

    // 设置 CURL 选项
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HEADER, false);

    // 输出当前工作目录
    \App\Utils\MyLog::info('当前工作目录: ' . getcwd());

    // 输出上传文件路径
    \App\Utils\MyLog::info('上传文件路径: ' . $filePath);

    // 检查文件是否存在
    if (!file_exists($filePath)) {
        throw new \Exception('文件不存在: ' . $filePath);
    }
    if (filesize($filePath) === 0) {
        throw new \Exception('文件为空: ' . $filePath);
    }
    \App\Utils\MyLog::info('文件大小'.json_encode(filesize($filePath) ));
    // 文件上传
    $cfile = new CURLFile($filePath);
    if (!$cfile instanceof CURLFile) {
        throw new \Exception('CURLFile 对象创建失败');
    }
    $data = [
        'files' => $cfile,
        'path' => $additionalParam
    ];
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    \App\Utils\MyLog::info('推送到服务器');

    // 执行 CURL 请求
    $response = curl_exec($curl);
    \App\Utils\MyLog::info('返回请求' . json_encode($response));

    if (curl_errno($curl)) {
        throw new \Exception('Curl error: ' . curl_error($curl));
    }

    curl_close($curl);
    return $response; // 可根据需要处理响应
}



function getEquipName($equips,$itemId)
{
    $equip = collect($equips)->where('id','=',$itemId)->first();
    return data_get($equip,'name',$itemId);
}

function getOpTypeName($opTypeList,$opType){
    $opType = collect($opTypeList)->where('id','=',$opType)->first();
    return data_get($opType,'name',$opType);
}
function getAttrName($attrs,$key){
    $attr = collect($attrs)->where('id',$key)->first();
    return data_get($attr,'name');
}

function urlencodedStrToArray($urlencodedStr){
    $data = [];
    $array = explode('&',$urlencodedStr);
    foreach($array as $item){
        $arr = explode('=',$item);
        $data[$arr[0]] = urldecode($arr[1]);
    }
    return $data;
}


/** ?k=v&k1=v1....
 * @param array $data
 * @return string
 */
function dataToParams($data){
    ksort($data);
    $str = '';
    foreach($data as $key=>$value){
        if (is_array($value) ) {
            $value = json_encode($value);
        }
        $str .= "&" . $key . "=" . $value ;
    }
    $str = substr($str,1);
    return $str;
}

function dataToParamsAndEncoded($data){
    ksort($data);
    $str = '';
    foreach($data as $key=>$value){
        $str .= "&" . $key . "=" . urlencode($value) ;
    }
    $str = substr($str,1);
    return $str;
}


/**
 * @param $url
 * @param string $data
 * @param array $headers
 * @return bool|string
 */
function httpPost($url,$data,$headers=[])
{

    $curl = curl_init(); // 启动一个CURL会话
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    curl_setopt($curl, CURLOPT_POST, true); // 发送一个常规的Post请求
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
    curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
    curl_setopt($curl, CURLOPT_HEADER, false); // 显示返回的Header区域内容
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 获取的信息以文件流的形式返回
    if (!empty($headers)) {
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    }
    $result = curl_exec($curl); // 执行操作
    if (curl_errno($curl)) {
        return 'Error POST'.curl_error($curl);
    }
    curl_close($curl); // 关键CURL会话
    return $result; // 返回数据
}

/**
 * 通过一个链接地址返回雪花算法UUID, 地址为java提供的服务,xm2Uuid为docker容器名称,保证了高并发场景下ID唯一性
 * @return int 64
 */
function getSnowFlakeId()
{
    while(true){
        try {
            $client = new Client();
            $result = $client->get("xm2Uuid:8111/index/getUuid");
            $content = $result->getBody()->getContents();
            $map = json_decode($content,true);
            return data_get($map,'uuid');
        } catch (Exception $e) {
            continue;
        }
    }
}

function calculateAgeByIDCard($idCard) {
    $birthDate = substr($idCard, 6, 8); // 提取出生日期
    $year = substr($birthDate, 0, 4);
    $month = substr($birthDate, 4, 2);
    $day = substr($birthDate, 6, 2);
    $birthDateTime = strtotime("$year-$month-$day"); // 将日期转换为时间戳
    $currentDateTime = time(); // 获取当前时间戳
    $age = floor(($currentDateTime - $birthDateTime) / (365 * 60 * 60 * 24)); // 计算年龄
    return $age;
}


